/**
 * tron_tx.cpp
 *
 * This programs transmits the on/off packets.
 *
 * Author: Charles DuHadway
 * email: duhadway@gmail.com


 * TODO:
 *   X get serial transmision working	
 *   X get port2 buttons working
 *   X get all button working
 *   X add debounce logic
 *   turn BIT6 back to input
 *   look at internal pull-up resistors (P1REN)
 */

#include "../common.h"
#include <msp430g2553.h>
#include <legacymsp430.h>
#include <stdint.h>

// PORT 1
#define FORWARD  BIT5
#define BACKWARD BIT4
#define ALL_OFF  BIT0

// PORT 2
#define ALL_ON   BIT0

uint8_t p1_buttons = (FORWARD | BACKWARD | ALL_OFF);
uint8_t p2_buttons = (ALL_ON);

uint8_t alan = 0;
uint8_t charles = 1;
uint8_t dave = 2;
uint8_t hansel = 3;
uint8_t ken = 4;
uint8_t seth = 5;

uint8_t guzel = 6;
uint8_t kelly = 7;
uint8_t kristina = 8;
uint8_t laura = 9;
uint8_t linda = 10;
uint8_t maria = 11;

// Simple cues
uint8_t cues[9][12] = {
//  A, C, D, H, K, S,  G, Ke, Kr, La, Li, M
  { 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0, 0 },  // All off
                                                // Intro
  { 0, 0, 1, 0, 0, 1,  0,  0,  0,  0,  0, 0 },  //   Dave and Seth light up
  { 0, 0, 1, 1, 0, 1,  0,  0,  0,  0,  0, 0 },  //   Hansel lights up
  { 1, 0, 1, 1, 1, 1,  0,  0,  0,  0,  0, 0 },  //   Alan and Ken light up
  { 1, 1, 1, 1, 1, 1,  0,  0,  0,  0,  0, 0 },  //   Charles lights up
  { 1, 1, 1, 1, 1, 1,  1,  1,  1,  1,  1, 1 },  //   Ladies turn on after dresses rip down
                                                // Tag
  { 0, 1, 0, 0, 0, 0,  0,  0,  0,  0,  0, 0 },  //   Everyone off except Charles
  { 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0, 0 },  // All off
  { 1, 1, 1, 1, 1, 1,  1,  1,  1,  1,  1, 1 },
};

uint8_t complex_cues[29][12] = { // TODO
//  A, C, D, H, K, S,  G, Ke, Kr, La, Li, M
  { 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0, 0 },  // All off
                                                // Intro
  { 0, 0, 1, 0, 0, 1,  0,  0,  0,  0,  0, 0 },  //   Dave and Seth light up
  { 0, 0, 1, 1, 0, 1,  0,  0,  0,  0,  0, 0 },  //   Hansel lights up
  { 1, 0, 1, 1, 1, 1,  0,  0,  0,  0,  0, 0 },  //   Alan and Ken light up
  { 1, 1, 1, 1, 1, 1,  0,  0,  0,  0,  0, 0 },  //   Charles lights up
  { 1, 1, 1, 1, 1, 1,  1,  1,  1,  1,  1, 1 },  //   Ladies turn on after dresses rip down
                                                // V-Waltz
  { 1, 1, 1, 1, 1, 1,  1,  1,  1,  1,  1, 1 },  //   Men blink during robot section
  { 0, 0, 0, 0, 0, 0,  0,  1,  1,  1,  1, 1 },
  { 1, 1, 1, 1, 1, 1,  1,  1,  1,  1,  1, 1 },
  { 0, 0, 0, 0, 0, 0,  0,  1,  1,  1,  1, 1 },
  { 1, 1, 1, 1, 1, 1,  1,  1,  1,  1,  1, 1 },
                                                // Tango #1

                                                // FoxTrot
  { 1, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0, 1 },  //   Everyone off but solo couple
  { 1, 1, 1, 1, 1, 0,  1,  1,  1,  1,  0, 1 },  //   Couples turn off in ripple, Linda + Seth
  { 1, 1, 1, 0, 1, 0,  0,  1,  1,  1,  0, 1 },  //     Hansel + Guzel
  { 1, 0, 1, 0, 1, 0,  0,  0,  1,  1,  0, 1 },  //     Charles + Kelly
  { 1, 0, 0, 0, 1, 0,  0,  0,  0,  1,  0, 1 },  //     Dave + Kristina
  { 1, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0, 1 },  //     Ken + Laura

                                                // Quickstep
  { 1, 0, 0, 0, 0, 1,  0,  0,  0,  0,  0, 1 },  //   Everyone on floor lights up when men slide in: Seth
  { 1, 0, 0, 1, 0, 1,  0,  0,  0,  0,  0, 1 },  //     Hansel
  { 1, 1, 0, 1, 0, 1,  0,  0,  0,  0,  0, 1 },  //     Charles
  { 1, 1, 1, 1, 0, 1,  0,  0,  0,  0,  0, 1 },  //     Dave
  { 1, 1, 1, 1, 1, 1,  0,  0,  0,  0,  0, 1 },  //     Ken
  { 1, 1, 1, 1, 1, 1,  1,  1,  1,  1,  1, 1 },  //   Lights move up the bodice to the beat (Just ON for now)
  { 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0, 0 },  //   All lights out while running to line
  { 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0, 0 },  //   Ripple down the line for 6 counts: 

  { 1, 1, 1, 1, 1, 1,  1,  1,  1,  1,  1, 1 },  //   Lights on after slash

                                                // Waltz

                                                // Tango #2

                                                // Tag
  { 0, 1, 0, 0, 0, 0,  0,  0,  0,  0,  0, 0 },  //   Everyone off except Charles
  { 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0, 0 },  // All off
  { 1, 1, 1, 1, 1, 1,  1,  1,  1,  1,  1, 1 },
};

int cue_index = 0;
int cue_count = 9;

long int debounce_count = 0;

void serial_xmit(uint8_t c) {
  while (!(IFG2 & UCA0TXIFG)); // USCI_A0 TX buffer 
  UCA0TXBUF = (uint8_t) c;     // TX -> RXed character
  _NOP();
}

void interrupt_handler(void) {

  if (debounce_count > 0) {    
    P1IFG = 0x0;
    P2IFG = 0x0;
    _NOP();
    return;
  }

  debounce_count = 10;

  if (P1IFG & FORWARD) {
    P1IFG &= ~FORWARD;
    cue_index = (cue_index + 1) % cue_count;
  }

  if (P1IFG & BACKWARD) {
    P1IFG &= ~BACKWARD;
    cue_index = (cue_index + cue_count - 1) % cue_count;
  }

  if (P2IFG & ALL_ON) {
    P2IFG &= ~ALL_ON;
    cue_index = cue_count - 1;
  }

  if (P1IFG & ALL_OFF) {
    P1IFG &= ~ALL_OFF;
    cue_index = 0;
  }

}


int main(void)
{
  WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
 
  BCSCTL1 = CALBC1_8MHZ;
  DCOCTL = CALDCO_8MHZ;

  P1SEL = BIT2;  // P1.2=TXD
  P1SEL2 = BIT2; // P1.2=TXD

  UCA0CTL1 = 0;		// Resetting to known state (nothing)
  UCA0CTL1 |= UCSSEL_2; // use SMCLK for USCI clock

  UCA0BR0 = 104 & 0xFF;        // 8MHz 4800
  UCA0BR1 = 104 >> 8;          // 8MHz 4800

  UCA0MCTL = 0x1; // UCOS16 = 1 , UCBRS=0, 

  UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
  IE2 |= UCA0RXIE;      // Enable USCI0RX_ISR interrupt

  P1DIR = ~p1_buttons; // Set P1 buttons input
  P2DIR = ~p2_buttons; // Set P2 buttons input

  P1IE = p1_buttons; // P1 buttons interrupt enabled
  P2IE = p2_buttons; // P2 buttons interrupt enabled

  P1IES = ~p1_buttons;
  P2IES = ~p2_buttons;

  P1IFG &= ~p1_buttons; // P1 IFG cleared
  P2IFG &= ~p2_buttons; // P2 IFG cleared

  P1OUT |= (BIT0);

  __bis_SR_register(GIE);  // Enable interrupts.

  debounce_count = 0;

  while (1) {
    debounce_count = (debounce_count > 0) ? debounce_count - 1 : 0;

    serial_xmit(FILLER);

    int current_cue = cue_index;    
    if (cues[current_cue][alan]) {
      P1OUT |= BIT6;
    } else {
      P1OUT &= ~BIT6;
    }

    if (cues[current_cue][alan])    serial_xmit(ALAN_ON); else    serial_xmit(ALAN_OFF);
    if (cues[current_cue][charles]) serial_xmit(CHARLES_ON); else serial_xmit(CHARLES_OFF);
    if (cues[current_cue][dave])    serial_xmit(DAVE_ON); else    serial_xmit(DAVE_OFF);
    if (cues[current_cue][hansel])  serial_xmit(HANSEL_ON); else  serial_xmit(HANSEL_OFF);
    if (cues[current_cue][ken])     serial_xmit(KEN_ON); else     serial_xmit(KEN_OFF);
    if (cues[current_cue][seth])    serial_xmit(SETH_ON); else    serial_xmit(SETH_OFF);

    if (cues[current_cue][guzel])    serial_xmit(GUZEL_ON); else    serial_xmit(GUZEL_OFF);
    if (cues[current_cue][kelly])    serial_xmit(KELLY_ON); else    serial_xmit(KELLY_OFF);
    if (cues[current_cue][kristina]) serial_xmit(KRISTINA_ON); else serial_xmit(KRISTINA_OFF);
    if (cues[current_cue][laura])    serial_xmit(LAURA_ON); else    serial_xmit(LAURA_OFF);
    if (cues[current_cue][linda])    serial_xmit(LINDA_ON); else    serial_xmit(LINDA_OFF);
    if (cues[current_cue][maria])    serial_xmit(MARIA_ON); else    serial_xmit(MARIA_OFF);
  }
  return 0;
}

interrupt(PORT1_VECTOR) Port_1(void)
{
  interrupt_handler();
}

interrupt(PORT2_VECTOR) Port_2(void)
{
  interrupt_handler();
}

